package com.example.login.username;

import com.example.controller.RegisteredClientController;
import com.example.exception.BaseException;
import com.example.redis.CaptchaRedis;
import com.example.utils.JSON;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import java.io.IOException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 用户名密码登录
 * AbstractAuthenticationProcessingFilter 的实现类要做的工作：
 * 1. 从HttpServletRequest提取授权凭证。假设用户使用 用户名/密码 登录，就需要在这里提取username和password。
 * 然后，把提取到的授权凭证封装到的Authentication对象，并且authentication.isAuthenticated()一定返回false
 * 2. 将Authentication对象传给AuthenticationManager进行实际的授权操作
 */
public class UsernameAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    private static final Logger logger = LoggerFactory.getLogger(UsernameAuthenticationFilter.class);
    private CaptchaRedis captchaRedis;


    public UsernameAuthenticationFilter(AntPathRequestMatcher pathRequestMatcher,
                                        AuthenticationManager authenticationManager,
                                        AuthenticationSuccessHandler authenticationSuccessHandler,
                                        AuthenticationFailureHandler authenticationFailureHandler,
                                        CaptchaRedis captchaRedis) {
        super(pathRequestMatcher);
        setAuthenticationManager(authenticationManager);
        setAuthenticationSuccessHandler(authenticationSuccessHandler);
        setAuthenticationFailureHandler(authenticationFailureHandler);

        this.captchaRedis = captchaRedis;

    }


    /**
     * 解析 application/x-www-form-urlencoded 格式的请求体
     */
    private Map<String, String> parseFormData(HttpServletRequest request) throws IOException {
        Map<String, String> formData = new HashMap<>();
        String body = request.getReader().lines()
                .collect(Collectors.joining(System.lineSeparator()));

        // 分割键值对
        String[] pairs = body.split("&");
        for (String pair : pairs) {
            int idx = pair.indexOf("=");
            if (idx > 0 && idx < pair.length() - 1) {
                String key = URLDecoder.decode(pair.substring(0, idx), StandardCharsets.UTF_8);
                String value = URLDecoder.decode(pair.substring(idx + 1), StandardCharsets.UTF_8);
                formData.put(key, value);
            }
        }
        return formData;
    }


    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException, IOException, ServletException {
        String captcha = captchaRedis.get(request.getParameter("uuid"));
        String inputCaptcha = request.getParameter("captcha");

        if (captcha == null || !captcha.equalsIgnoreCase(inputCaptcha)) {
            throw new BadCredentialsException("验证码错误");
        }

        String username;
        String password;

        // 检查请求的内容类型
        if ("application/x-www-form-urlencoded".equals(request.getContentType())) {
            // 1. 解析请求体中的表单数据
//            Map<String, String> formData = parseFormData(request);
//
//            // 2. 提取用户名和密码
            username = request.getParameter("username");
            password = request.getParameter("password");

        } else {
            // 提取请求数据
            String requestJsonData = request.getReader().lines()
                    .collect(Collectors.joining(System.lineSeparator()));
            Map<String, Object> requestMapData = JSON.parseToMap(requestJsonData);
            username = requestMapData.get("username").toString();
            password = requestMapData.get("password").toString();
        }

        // 3. 校验数据是否为空
        if (username == null || password == null) {
            throw new BadCredentialsException("用户名密码丢失");
        }
        // 封装成Spring Security需要的对象
        UsernameAuthentication authentication = new UsernameAuthentication();
        authentication.setUsername(username);
        authentication.setPassword(password);
        authentication.setAuthenticated(false);

        // 开始登录认证。SpringSecurity会利用 Authentication对象去寻找 AuthenticationProvider进行登录认证
        return getAuthenticationManager().authenticate(authentication);
    }
}
